#ifndef UTIL_HPP_
#define UTIL_HPP_
#include <iostream>
#include <vector>

using namespace std;

class Util
{
public:
	Util(){
	}
	virtual ~Util(){
	}	
	
	/**@return a random int btw low and high */
	template <class T>
	T generate_random_number(int low, int high);	
	
	/** @return a vector of n integers */
	template <class T>		
	vector<T> generate_random_numbers(int n, int low, int high);
	
	/** @return true if a vector contains a specified element */
	template <class T>		
	bool is_contain(vector<T> a_vector, T element);

	template <class T>
	float compute_sum(vector<T> samples);

	template <class T>
	float compute_mean(vector<T> samples);

	template <class T>
	float compute_variance(vector<T> samples);
			
	template <class T>
	void print_vector(vector<T> a_vector);	
};

template <class T>
bool Util::is_contain(vector<T> a_vector, T element){
	typename vector<T>::iterator pos;
	
	for (pos = a_vector.begin(); pos != a_vector.end(); ++pos) {
        if (*pos == element) return true; 
   	 }
    
	return false;
}

template <class T>
T  Util::generate_random_number(int low, int high){
	srand(time(NULL));
	T random_number	= (((T)(((double)rand()/(double)(RAND_MAX+1))*(high-low)))*-1)+1;	
	
	return random_number;
}

/**
 * @param n	size of numbers
 * @param low low range
 * @param high high range
 */
template <class T>
vector<T> Util::generate_random_numbers(int n, int low, int high){
	vector<T> random_numbers;
	srand(time(NULL));
	for ( int i=0; i < n; i++ ){
		T random_number	= (((T)(((double)rand()/(double)(RAND_MAX+1))*(high-low)))*-1)+1;
		
		random_numbers.push_back(random_number);
	}
		
	return random_numbers;
}

template <class T>
void Util::print_vector(vector<T> a_vector){
	class vector<T>::iterator pos;
	for (pos = a_vector.begin(); pos != a_vector.end(); ++pos) {
		cout << *pos << endl;
	}
}

template <class T>
float Util::compute_sum(vector<T> samples){
	typename vector<T>::iterator pos;
	
	float sum = 0;
	for ( pos= samples.begin(); pos != samples.end(); ++pos ){
		//cout << "get a int value " << *pos << endl;
		sum += (T)(*pos);
	}
	
	return sum;	
}

template <class T>
float Util::compute_mean(vector<T> samples){
	int size = samples.size();
	float sum	 = compute_sum(samples);	
	float mean = sum/size;
	
	return mean;
}

template <class T>
float Util::compute_variance(vector<T> samples){
	float variance	= 0.0;
	
	float mean = compute_mean(samples);
	
	//printf("mean is: %f\n", mean);
	
	typename vector<T>::iterator pos;

	for (pos=samples.begin(); pos!=samples.end(); ++pos){
		T sample_value = *pos;
		variance += (sample_value-mean)*(sample_value-mean);
	}

	return (float)variance/(float)samples.size();
}

#endif /*UTIL_HPP_*/